package demo20;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

// 放的元素类型是 Long 类型
public class MyBlockingQueueV2 {
    private Long[] items;
    private int tailIndex;
    private int headIndex;
    private int size;
    private Lock lock;
    private Condition notEmpty;
    private Condition notFull;

    public MyBlockingQueueV2(int capacity){
        items = new Long[capacity];
        headIndex = 0;
        tailIndex = 0;
        size = 0;
        lock = new ReentrantLock();
        notEmpty = lock.newCondition();
        notFull = lock.newCondition();
    }

    public synchronized void put(Long e) throws InterruptedException {
        lock.lock();
        try {
            // 先不考虑阻塞，先搞定循环
            while (size == items.length) {
                // 满了
                notFull.await();
            }

            items[tailIndex] = e;
            tailIndex++;
            if (tailIndex == items.length) {
                tailIndex = 0;
            }

            notEmpty.signal();

            size++;
        } finally {
            lock.unlock();
        }
    }

    public synchronized Long take() throws InterruptedException {
        lock.lock();
        try {
            while (size == 0) {
                notEmpty.await();    // 希望生产者唤醒
            }
            Long e = items[headIndex];
            headIndex++;
            if (headIndex == items.length) {
                headIndex = 0;
            }
            size--;

            notFull.signal();   // 希望唤醒的是生产者

            return e;
        } finally {
            lock.unlock();
        }
    }


}
